#include "master.h"
#include <shlwapi.h>
#include <dshow.h>
#include <shlobj.h>
#include "mediadet.h"
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "menu.h"
#include "misc.h"
#include "systray.h"
#include "stream.h"
#include "flags.h"
#include "comfunct/comfunct.h"
#include "metaparse.h"
#include "gui.h"

void Cleanup(HWND hwnd, short sOptions)
{
     if(sOptions & IS_TRAYED)
     {
         DeleteTrayIcon(hwnd);
     }
	 if(sOptions & MEDIA_HOOK)
	 {
		 SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_TOOLS_MEDIAHOOK, 0), 0);
	 }
     
     ToggleHotKeys(hwnd, false);
     
     MSNCheckAndUpdate(hwnd, NULL, true);
     return;
}

void ShutdownPrivilege()
{
     HANDLE hToken;
     TOKEN_PRIVILEGES tp = {0};
     HMENU hParentMenu = GetMenu(GetAPWindow()), hControlMenu = NULL;
     
     OpenProcessToken(GetCurrentProcess(), TOKEN_WRITE | TOKEN_QUERY, &hToken);
                    
     LookupPrivilegeValue(TEXT(""), TEXT("SeShutdownPrivilege"), &tp.Privileges[0].Luid);
     tp.PrivilegeCount = 1;
     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
                    
     if(AdjustTokenPrivileges(hToken, false, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0) != 0 && GetLastError() != ERROR_SUCCESS)
     {
         hControlMenu = GetSubMenu(hParentMenu, CONTROL_MENU);
         EnableMenuItem(hControlMenu, IDI_HELP_LOGOFF, MF_BYCOMMAND | MF_DISABLED);
         EnableMenuItem(hControlMenu, IDI_HELP_REBOOT, MF_BYCOMMAND | MF_DISABLED);
         EnableMenuItem(hControlMenu, IDI_HELP_SHUTDOWN, MF_BYCOMMAND | MF_DISABLED);
     }
     CloseHandle(hToken);
     return;
}

bool IsMPEGAudio(LPTSTR szUrlName)
{
     LPCTSTR szUrlExt = PathFindExtension(szUrlName);
     
#ifdef UNICODE /* Windows 2000/XP support LOCALE_INVARIANT */
     
     if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mp3"), -1) == CSTR_EQUAL)
     {
          return true;
     }
     else if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mp2"), -1) == CSTR_EQUAL)
     {
          return true;
     }
     else if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mpa"), -1) == CSTR_EQUAL)
     {
          return true;
     }
	 else if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mpga"), -1) == CSTR_EQUAL)
     {
          return true;
     }
     else return false;
     
#else /* Windows 98 doesn't */

     if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mp3"), -1) == CSTR_EQUAL)
     {
          return true;
     }
     else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mp2"), -1) == CSTR_EQUAL)
     {
          return true;
     }
     else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mpa"), -1) == CSTR_EQUAL)
     {
          return true;
     }
	 else if(CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_IGNOREWIDTH, szUrlExt, -1, TEXT(".mpga"), -1) == CSTR_EQUAL)
     {
          return true;
     }
     else return false;
     
#endif
}

void GetSavePath(HWND hwnd)
{
     OPENFILENAME ofn = {0};
     TCHAR szSaveFileName[MAX_PATH] = TEXT(".mp3");
     TCHAR szMyMusic[MAX_PATH] = TEXT("");
     
	 GetMyMusicDir(hwnd, szMyMusic);
     
     ofn.lStructSize = sizeof(OPENFILENAME);
	 ofn.hwndOwner = hwnd;
	 ofn.lpstrFilter = GetLocalText(28);
	 ofn.lpstrFile = szSaveFileName;
	 ofn.nFilterIndex = 1;
	 ofn.lpstrTitle = GetLocalText(29);
	 ofn.nMaxFile = MAX_PATH;
	 ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_NONETWORKBUTTON;
	 ofn.lpstrDefExt = TEXT("mp3");
	 ofn.lpstrInitialDir = szMyMusic;
	 
	 if(GetSaveFileName(&ofn))
	 {
         SaveAudioStream(NULL, szSaveFileName);
         return;
     }
     else if(CommDlgExtendedError()== 0)
	 {
         return;
     }
}

void UnmapMemory()
{
	extern LPTSTR lpSharedMem;
	extern HANDLE hMemMap;
    UnmapViewOfFile(lpSharedMem);
    lpSharedMem = NULL;
    CloseHandle(hMemMap);
	return;
}

bool IsFileAudio(LPCTSTR szFileName)
{
	BSTR wideszFileName = 0;
	const GUID AudioGUID = MEDIATYPE_Audio;
	GUID GUIDStreamType = {0};
	long lNumStreams = 0;
	WCHAR* wszTempName = NULL;
	HRESULT hr = 0;
	IMediaDet *pDetect = NULL;
	
#ifdef UNICODE

    wideszFileName = SysAllocString(szFileName);
    
#else

    wszTempName = UnicodeConversion(szFileName);
    wideszFileName = SysAllocString(wszTempName);
    FreePointer(wszTempName);
    
#endif

    hr = CoCreateInstance(&CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER, &IID_IMediaDet, (void**)&pDetect);
    if(FAILED(hr))
    {
        HRErrorInfo(hr); 
		SysFreeString(wideszFileName);
		SAFE_RELEASE(pDetect);
        return false;
    }

    hr = pDetect->lpVtbl->put_Filename(pDetect, wideszFileName);
    SysFreeString(wideszFileName);
	if(FAILED(hr))
	{
		HRErrorInfo(hr);
		SAFE_RELEASE(pDetect);
		return false;
	}

    pDetect->lpVtbl->get_OutputStreams(pDetect, &lNumStreams);
	if(lNumStreams == 0L)
	{
		SAFE_RELEASE(pDetect);
		return false;
	}

	pDetect->lpVtbl->put_CurrentStream(pDetect, 1L);
	hr = pDetect->lpVtbl->get_StreamType(pDetect, &GUIDStreamType);
	
	if(FAILED(hr))
	{
		HRErrorInfo(hr);
		SAFE_RELEASE(pDetect);
		return false;
	}

	if(!IsEqualGUID(&AudioGUID, &GUIDStreamType))
	{
		SAFE_RELEASE(pDetect);
		DShowRelease();
		return false;
    }
    else
    {
        SAFE_RELEASE(pDetect);
		return true;
    }
}

void ToggleDesktopLink()
{
	IShellLink* iShlink = NULL;
	TCHAR szAudioPlayerPath[MAX_PATH] = TEXT("");

	GetModuleFileName(NULL, szAudioPlayerPath, MAX_PATH);

	if(SUCCEEDED(CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void**)&iShlink)))
	{
		LPCTSTR szDesc = GetLocalText(30);
		IPersistFile* iPFile = NULL;

		iShlink->lpVtbl->SetPath(iShlink, szAudioPlayerPath);
		iShlink->lpVtbl->SetDescription(iShlink, szDesc);
		iShlink->lpVtbl->SetIconLocation(iShlink, szAudioPlayerPath, 0);

		if(SUCCEEDED(iShlink->lpVtbl->QueryInterface(iShlink, &IID_IPersistFile, (void**)&iPFile)))
		{
			TCHAR szDesktopLinkPath[MAX_PATH] = TEXT("");
			WCHAR* wideszDesktopPath = NULL;

			if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, szDesktopLinkPath)))
			{
				PathAppend(szDesktopLinkPath, TEXT("AudioPlayer.lnk"));
			}

			if(PathFileExists(szDesktopLinkPath))
			{
				DeleteFile(szDesktopLinkPath);
				MessageBox(NULL, GetLocalText(31), TEXT("AudioPlayer"), MB_OK | MB_ICONINFORMATION);
				SAFE_RELEASE(iShlink);
				SAFE_RELEASE(iPFile);
				return;
			}
			
#ifndef UNICODE

            wideszDesktopPath = UnicodeConversion(szDesktopLinkPath);
			iPFile->lpVtbl->Save(iPFile, wideszDesktopPath, TRUE);
			FreePointer(wideszDesktopPath);
#else

			iPFile->lpVtbl->Save(iPFile, szDesktopLinkPath, TRUE);

#endif

			MessageBox(NULL, GetLocalText(32), TEXT("AudioPlayer"), MB_OK | MB_ICONINFORMATION);
			SAFE_RELEASE(iPFile);
		}
		SAFE_RELEASE(iShlink);
	}
	return;
}

bool ParseCommandLine(LPTSTR szParams, size_t s_tParamsLength, HWND hwnd)
{
     bool bHideWindow = false;
	 extern bool bCmdLine;
     size_t s_tParamsPosition = 0;
	 TCHAR* cTokenPos = NULL;
     TCHAR* szParamsCopy = malloc(sizeof(TCHAR) * (_tcslen(szParams) + 2)); 
	 szParamsCopy[0] = TEXT(' ');
	 _tcscpy(szParamsCopy + 1, szParams);

	 cTokenPos = _tcstok(szParamsCopy + 1, TEXT("-"));

	 while(cTokenPos != NULL)
	 {
		 if(*(cTokenPos - 2) == TEXT(' ')) /* Filter out paths that have '-' is them, not perfect but it'll do for now  */
		 {
			 switch(cTokenPos[0])
			 {
				case 'h': /* Hide the main window */
				{
                    if(tolower(cTokenPos[1]) == 'a') /* Hide all instances if -ha is specified */
                    {
                        DWORD dwTarget = BSM_APPLICATIONS;
                        BroadcastApMessage(&dwTarget, AP_HIDE);
                    }
                    else if(tolower(cTokenPos[1]) == 'c') /* Hide all instances but close this one */
                    {
                        DWORD dwTarget = BSM_APPLICATIONS;
                        BroadcastApMessage(&dwTarget, AP_HIDE);
                        SendMessage(hwnd, WM_CLOSE, 0, 0);
                    }
                    else
                    {
                        bHideWindow = true;
                        ToggleHotKeys(hwnd, true);
                    }
               }
               break;
               case 'c': /* Close all other instances including this one */
               {
                    DWORD dwTarget = BSM_APPLICATIONS;
                    BroadcastApMessage(&dwTarget, AP_CLOSE);
               }
               break;
               case 's': /* Show other instances and close this one */
               {
                    DWORD dwTarget = BSM_APPLICATIONS;
                    BroadcastApMessage(&dwTarget, AP_SHOW);
                    SendMessage(hwnd, WM_CLOSE, 0, 0);
               }
               break;
               case 'l':
			   {
                    SendMessage(hwnd, WM_NULL, AP_LOOP, 0);
               }
               break;
			   case 'r':
			   {
				   SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_PLAYLIST_SHUFFLE, 0), 0);
			   }
			   break;
               case 'x':
               {
                    SendMessage(hwnd, WM_CLOSE, 0, 0);
               }
               break;
               case 't':
               {
                    SendMessage(hwnd, WM_NULL, AP_TRAY, 0);
					MenuCheck(hwnd, FILE_MENU, IDI_FILE_MINTOTRAY, true);
                    ShowWindow(hwnd, SW_MINIMIZE);
                    bHideWindow = true;
               }
               break;
               case 'e':
               {
                    SendMessage(hwnd, WM_NULL, AP_CLOSEONFINISH, 0);
               }
               break;
               case 'o':
               {
                    size_t s_tPathLength = 0;
                    LPTSTR szFileNameStart = cTokenPos + 2; /* Get a pointer to the beginning of the path string after the "-o " */
                    TCHAR szFullFilePath[MAX_PATH] = TEXT("");
                    
                    if(szFileNameStart[0] != TEXT('"')) // The path isn't surrounded by quotes
                    {
                        TCHAR szFilePath[MAX_PATH] = TEXT("");
						_stscanf(szFileNameStart, TEXT("%s"), szFilePath);
						if(PathFileExists(szFilePath) == FALSE)
                        {
                            ErrorMessage(GetLocalText(33));
                            break;
                        }
						GetFullPathName(szFilePath, MAX_PATH, szFullFilePath, NULL); // essentially concatenates the path we read onto the current directory
                    }
					else 
					{
						TCHAR* szClosingQuote = (_tcschr(szFileNameStart + 1, TEXT('"')) + 1); // Get a pointer to the element after the closing quotation mark
						size_t s_tNoChars = szClosingQuote - szFileNameStart; // Find how long the string is
						_tcsncpy(szFullFilePath, szFileNameStart, s_tNoChars); // copy that many characters from the starting quote into the szFullFilePath buffer
					}
					CommandLineOpen(szFullFilePath, hwnd);
               }
               break;
			 }
		 }
		 cTokenPos = _tcstok(NULL, TEXT("-")); // Find the next - in the parameter list and start again
	 }
	 bCmdLine = true;
	 free(szParamsCopy);
     return bHideWindow;
}

void BroadcastApMessage(LPDWORD dwTarget, int AP_MSG)
{
    BroadcastSystemMessage(BSF_FORCEIFHUNG, dwTarget, WM_NULL, AP_MSG, 0);
    /* Since the message specified here will be sent to all windows, WM_NULL has been chosen
    *  to minimize conflicts with other applications */
}

void MSNCheckAndUpdate(HWND hwnd, LPTSTR szFileName, bool bClear)
{
	WCHAR wszMSNString[300] = L"";
	COPYDATASTRUCT cds = {0};
	HWND hMSNWindow = NULL;
	MENUITEMINFO mii = {0};
	HMENU hMenu = GetMenu(hwnd), hToolsMenu = GetSubMenu(hMenu, TOOLS_MENU);
	WCHAR* wszWideFileName = NULL;
	TCHAR* szExtension = NULL;
	IWMMetadataEditor* MetaEdit = NULL;

	mii.cbSize = sizeof(MENUITEMINFO);
	mii.fMask = MIIM_STATE;

	GetMenuItemInfo(hToolsMenu, IDI_TOOLS_MSN, FALSE, &mii);

	if((mii.fState != MFS_CHECKED) && bClear == false) /* If the menu option isn't checked and we're not clearing the text, don't do anything */
	{
		return;
	}

	szExtension = PathFindExtension(szFileName);

#ifndef UNICODE

	wszWideFileName = UnicodeConversion(szFileName);
	MetaEdit = CreateReader(wszWideFileName);	

#else

	MetaEdit = CreateReader(szFileName);

#endif
	
	if(bClear == true)
	{
		_snwprintf(wszMSNString, 300, L"\\0Music\\00\\0{0} - {1}\\0\\0\\0\\0\\0");
	}
	else
	{
		WCHAR* wszArtist = NULL, *wszTitle = NULL;
		if(CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, szExtension, -1, TEXT(".mp3"), -1) == CSTR_EQUAL)
		{
			if(GetID3TagArtist(MetaEdit, &wszArtist) == true)
			{
				/* Very hackish workaround here so we can treat both failure 
				   and good results the same below and free the buffers without differentiating*/
				WCHAR wszFailure[] = L"No Artist Found";
				wszArtist = malloc(sizeof(wszFailure));
				wcscpy(wszArtist, wszFailure);
			}
			if(GetID3TagTitle(MetaEdit, &wszTitle) == true)
			{
				WCHAR wszFailure[] = L"No Title Found";
				wszTitle = malloc(sizeof(wszFailure));
				wcscpy(wszTitle, wszFailure);
			}
		}
		else
		{
			wszArtist = GetAttribute(MetaEdit, g_wszWMAuthor); /* g_wszWMAuthor/g_wszWMTitle are defined in the wmsdkidl.h header file */
			wszTitle = GetAttribute(MetaEdit, g_wszWMTitle);
		}
		_snwprintf(wszMSNString, 300, L"\\0Music\\02\\0{0} - {1}\\0%s\\0%s\\0\\0", wszArtist, wszTitle);
		free(wszArtist);
		free(wszTitle);
	}

	MetaEdit->lpVtbl->Close(MetaEdit);
	SAFE_RELEASE(MetaEdit);

	cds.dwData = 0x547;
	cds.cbData = (DWORD)((wcslen(wszMSNString) + 1) * sizeof(WCHAR));
	cds.lpData = wszMSNString;

	while((hMSNWindow = FindWindowEx(NULL, hMSNWindow, TEXT("MsnMsgrUIManager"), NULL)) != NULL)
	{
		SendMessage(hMSNWindow, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
	}

#ifndef UNICODE

	FreePointer(wszWideFileName);

#endif

	return;
}

bool CheckForUpdates(HWND hwnd, HMODULE* hUpdateModule)
{
     UPDATEPROC UpdateDialog = NULL;
     STOPPROC UpdateClean = NULL;
	 *hUpdateModule = LoadLibrary(TEXT("update.dll"));
     if(*hUpdateModule == NULL)
     {
         ErrorMessage(GetLocalText(34));
         return false;
     }
     UpdateDialog = (UPDATEPROC)GetProcAddress(*hUpdateModule, "UpdateDialog");
	 UpdateClean = (STOPPROC)GetProcAddress(*hUpdateModule, "UpdateClean");
     if(UpdateDialog == NULL || UpdateClean == NULL)
     {
          ErrorMessage(GetLocalText(35));
          return false;
     }
     if(UpdateDialog(hwnd, AUDIOPLAYER_VERSION) == NULL)
	 {
		UpdateClean();
		return false;
	 }
     return true;
}

void ToggleHotKeys(HWND hwnd, bool bOn)
{
     int i = 0;

     const short iKeyIdents[] = {0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF, 0x07FF, 0x08FF, 0x09FF};
     const char iKeyCodes[] = {0x40, 0x50, 0x55, 0x53, 0x59, 0x4D, VK_F4, 0x56, 0x4C, 0x4E};
     /* KeyCodes are: o - Open File(s), p - Play, u - Pause, s - Stop, y - Open / Change playlist,
                      m - Toggle Mute, F4 - Close the App, v - View(Show) Window, l - Toggle Looping,
                      n - Next playlist track */
     
     if(bOn == true)
     {
         for(; i < (sizeof(iKeyIdents) / sizeof(short)); i++)
         {
              RegisterHotKey(hwnd, iKeyIdents[i], MOD_ALT | MOD_SHIFT, iKeyCodes[i]);
         }
     }
     else
     {
         for(; i < (sizeof(iKeyIdents) / sizeof(short)); i++)
         {
             UnregisterHotKey(hwnd, iKeyIdents[i]);
         }
     }
     return;
}

bool CheckForOtherInstances(AP_DATACOPY* pAdc)
{
    HANDLE hMutex = CreateMutex(NULL, FALSE, TEXT("AudioPlayer"));
    if(GetLastError() != ERROR_ALREADY_EXISTS)
    {
        ReleaseMutex(hMutex);
        CloseHandle(hMutex);
        return false;
    }
    else
    {
        EnumWindows(APWindowCheckProc, (LPARAM)pAdc);
		return true;
    }
}

BOOL CALLBACK APWindowCheckProc(HWND hWindow, LPARAM lParam)
{
    AP_DATACOPY* pAdc = (AP_DATACOPY*)lParam;
    TCHAR szWindowTitle[12] = TEXT("");
    GetWindowText(hWindow, szWindowTitle, 12);
    if(_tcscmp(szWindowTitle, TEXT("AudioPlayer")) == 0)
    {
        if(hWindow != pAdc->hwnd) /* We found the other instance */
        {
            COPYDATASTRUCT cds = {0};
			size_t s_tNameLen = _tcslen(pAdc->szFileName) + 1;
			TCHAR* szFileToPlay = malloc(s_tNameLen * sizeof(TCHAR));
			_tcsncpy(szFileToPlay, pAdc->szFileName, s_tNameLen);

            cds.cbData = s_tNameLen * sizeof(TCHAR);
            cds.lpData = szFileToPlay;

			SendMessage(hWindow, WM_COPYDATA, (WPARAM)pAdc->hwnd, (LPARAM)&cds);
			free(szFileToPlay);
			SendMessage(pAdc->hwnd, WM_CLOSE, 0, 0);
			PostQuitMessage(0);
            return FALSE;
        }
    }
    return TRUE;
}

/* Still doesn't quite work
void ReadOptionsAndConfigure(HWND hwnd, short* sOptions)
{
    FILE* fOptions = NULL;
    TCHAR szAudioPlayerConfig[MAX_PATH] = TEXT("");
    
    GetModuleFileName(NULL, szAudioPlayerConfig, MAX_PATH);
	PathRemoveFileSpec(szAudioPlayerConfig);
	_tcscat(szAudioPlayerConfig, TEXT("\\config.txt"));
    
    fOptions = _tfopen(szAudioPlayerConfig, TEXT("r"));
    
    if(fOptions == NULL)
    {
        return;
    }    
    _ftscanf(fOptions, TEXT("%02x"), sOptions);
	fclose(fOptions);

	if(*sOptions & TRAY_MINIMIZE)
	{
		MenuCheck(hwnd, FILE_MENU, IDI_FILE_MINTOTRAY, true);
	}
	if(*sOptions & IS_TRAYED)
	{
		MenuCheck(hwnd, FILE_MENU, IDI_FILE_MINTOTRAY, true);
		SendMessage(hwnd, WM_SIZE, SIZE_MINIMIZED, 0);
		ShowWindow(hwnd, SW_HIDE);
	}
	if(*sOptions & HOTKEYS_ON)
	{
		MenuCheck(hwnd, TOOLS_MENU, IDI_TOOLS_HOTKEYS, true);
		ToggleHotKeys(hwnd, true);
	}
	if(*sOptions & SHOW_LYRICS)
	{
		*sOptions &= (~(SHOW_LYRICS));
		PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_DISPLAY_LYRICS, 0), 1);
	}
	return;
}

void SaveOptions(short sOptions)
{
	TCHAR szAudioPlayerConfig[MAX_PATH] = TEXT("");
	FILE* fOptions = NULL;
	
	sOptions &= (~(CLOSE_WHEN_FINISHED));
    sOptions &= (~(TIMER_ON));
    sOptions &= (~(INSTANCE_MUTEX));

	if(sOptions == 0)
	{
		return; /* No point saving if no options are set *//*
	}

	GetModuleFileName(NULL, szAudioPlayerConfig, MAX_PATH);
	PathRemoveFileSpec(szAudioPlayerConfig);

	_tcscat(szAudioPlayerConfig, TEXT("\\config.txt"));

	DeleteFile(szAudioPlayerConfig);

	fOptions = _tfopen(szAudioPlayerConfig, TEXT("w"));
	if(fOptions == NULL)
	{
		ErrorMessage(GetLocalText(36));
		return;
    }
	_tfprintf(fOptions, TEXT("%02x"), sOptions);
	fclose(fOptions);
	return;
}
*/
void CopyData(HWND hwnd, TCHAR* szText)
{
	HANDLE hMem = NULL;
	TCHAR* szClipboard = NULL;
	OpenClipboard(hwnd);
	EmptyClipboard();

	hMem = GlobalAlloc(GHND, (_tcslen(szText) + 1) * sizeof(TCHAR));
	szClipboard = GlobalLock(hMem);
	memcpy(szClipboard, szText, GlobalSize(hMem));
	GlobalUnlock(hMem);

#ifdef UNICODE

	SetClipboardData(CF_UNICODETEXT, hMem);

#else

	SetClipboardData(CF_TEXT, hMem);

#endif

	CloseClipboard();
	return;
}

void GetMyMusicDir(HWND hwnd, TCHAR* szMyMusicDir)
{
#ifndef UNICODE

	if(SUCCEEDED(SHGetFolderPath(hwnd, CSIDL_PERSONAL, NULL, 0, szMyMusicDir)))
	{
		PathAppend(szMyMusicDir, GetLocalText(27));
	}

#else
	
	SHGetFolderPath(hwnd, CSIDL_MYMUSIC, NULL, 0, szMyMusicDir);

#endif
	
	return;
}
